package com.ogawa.base.network;

import android.util.Log;

import androidx.annotation.NonNull;

import com.example.reslib.Constants;
import com.google.gson.Gson;
import com.ogawa.base.network.Event.Event;
import com.ogawa.base.network.Event.UpdataEvent;
import com.ogawa.base.network.bean.BeanOnline;
import com.ogawa.base.network.bean.BeanStateInfo;
import com.ogawa.base.network.bean.BeanToken;
import com.ogawa.base.network.bean.BeanUpdata;
import com.ogawa.base.network.security.Sign;

import java.io.IOException;
import java.lang.reflect.Field;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Retrofit 的管理类，对 Retrofit 进行进一步的封装
 */
public class RetrofitManager {

    private static final String TAG = "RetrofitManager";
    private static final int DEFAULT_TIMEOUT = 10;// 连接超时时间
    private static final int READ_TIMEOUT = 5;// 读取超时时间

    private static volatile RetrofitManager mInstance;

    private String uri;
    private String method;
    private String jsonBody;
    private ApiService mApiService;// 请求接口类

    /**
     * Retrofit 管理类的私有构造函数
     */
    private RetrofitManager() {
        // Log 信息
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(
                new HttpLoggingInterceptor.Logger() {
                    @Override
                    public void log(@NonNull String message) {
                        Log.i(TAG, "HttpLoggingInterceptor --- message = " + message);
                    }
                })
                .setLevel(HttpLoggingInterceptor.Level.BODY);
        // 拦截器
        Interceptor interceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                String appId = Constants.APP_ID;// appId
                String timeStamp = System.currentTimeMillis() + "";// 请求时间戳，精确到毫秒
                String requestId = UUID.randomUUID().toString();
                Log.e("requestId","appid=="+appId+"---timeStamp=="+timeStamp+"---requestId==="+requestId);
                StringBuilder builder = new StringBuilder();
                builder.append(method)
                        .append("\n")
                        .append(uri)
                        .append("\n")
                        .append(appId)
                        .append("\n")
                        .append(timeStamp)
                        .append("\n")
                        .append(requestId)
                        .append("\n")
                        .append(null == jsonBody ? "" : jsonBody);
                String token = "";
                Log.i(TAG, "RetrofitManager ----- token = " + token);
                String signature = Sign.signature(Constants.RSA_PRIVATE, builder.toString());// 签名
                Log.i(TAG, "RetrofitManager --- 签名前的字符串：stringSign = \n" + builder.toString());
                Log.i(TAG, "RetrofitManager --- 签名后的字符串：signature =\n " + signature);
                Request request = chain.request().newBuilder()
                        .addHeader("Content-Type", "application/json")
                        .addHeader("Authorization", appId)
                        .addHeader("x-timestamp", timeStamp)
                        .addHeader("x-request-id", requestId)
                        .addHeader("x-signature", signature)
                        .addHeader("x-token", null == token ? "" : token)
                        .build();
                return chain.proceed(request);
            }
        };
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .addInterceptor(interceptor)
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)//
                .build();
        ignoreSSLCheck(okHttpClient);
        Retrofit mRetrofit = new Retrofit.Builder()
                .baseUrl(Constants.API_SERVICE)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        mApiService = mRetrofit.create(ApiService.class);
    }
    /**
     * 解决部分android9.0手机 http 请求失败的问题
     */
    private void ignoreSSLCheck(OkHttpClient okHttpClient) {
        Log.e(TAG, "ignoreSSLCheck()");
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            }}, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        HostnameVerifier hostnameVerifier1 = (hostname, session) -> true;
        String workerClassName = "okhttp3.OkHttpClient";
        try {
            Class workerClass = Class.forName(workerClassName);
            Field hostnameVerifier = workerClass.getDeclaredField("hostnameVerifier");
            hostnameVerifier.setAccessible(true);
            hostnameVerifier.set(okHttpClient, hostnameVerifier1);
            Field sslSocketFactory = workerClass.getDeclaredField("sslSocketFactory");
            sslSocketFactory.setAccessible(true);
            sslSocketFactory.set(okHttpClient, sslContext.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置 uri
     *
     * @param uri
     */
    public void setUri(String uri) {
        this.uri = uri;
    }

    /**
     * 设置请求体
     *
     * @param object
     */
    public void setJsonBody(Object object) {
        if (object == null) {
            this.jsonBody = "";
        } else {
            this.jsonBody = new Gson().toJson(object);
        }
    }

    /**
     * 设置 method
     *
     * @param method
     */
    public void setMethod(String method) {
        this.method = method;
    }

    /**
     * 单例模式获取 Retrofit 的管理类
     *
     * @return
     */
    public static RetrofitManager getInstance() {
        if (null == mInstance) {
            synchronized (RetrofitManager.class) {
                if (null == mInstance) {
                    mInstance = new RetrofitManager();
                }
            }
        }
        return mInstance;
    }


    /**
     * 启动程序事件
     *
     * @param event
     * @param subscriber
     */
    public void sendCommondEvent(Event event, Subscriber<BaseResponse> subscriber) {
        mApiService.sendCommondEvent(event)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

    /**
     * 获取Token
     *
     * @param sn
     * @param subscriber
     */
    public void getTokenEvent(String sn, Subscriber<BaseResponse<BeanToken>> subscriber) {
        mApiService.getTokenEvent(sn)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

    /**
     * 获取
     *
     * @param sn
     * @param subscriber
     */
    public void getStateEvent(String sn,String params, Subscriber<BaseResponse<BeanStateInfo>> subscriber) {
        mApiService.getStateEvent(params,sn)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }


    /**
     * 获取在线状态
     *
     * @param params  设备序号或mac地址
     * @param isMac   是否查询mac 0否 1是
     */
    public void getOnlineEvent(String params,int isMac, Subscriber<BaseResponse<BeanOnline>> subscriber) {
        mApiService.getOnlineEvent(params,isMac)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);

    }

    /**
     * 启动升级事件
     *
     * @param event
     * @param subscriber
     */
    public void upDataEvent(UpdataEvent event, Subscriber<BaseResponse<BeanUpdata>> subscriber) {
        mApiService.UpdataEvent(event)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

}


